﻿//==============================================================================  
//Copyright (C) 2012-2015 9UN.ORG. All rights reserved. 
//GUID：d04d9160-f0ae-4fc4-a8d0-5637fc630c0c
//CLR Version: 4.0.30319.18033
//Code Author：Kevin Wang
//Contact：Email(Admin@9un.org),QQ(265382 or 74344)
//Filename：DocumentRender
//Namespace：RuanRang.Core
//Functions：BaseRenderProxy  
//Created by Kevin Wang at 2013/2/3 10:45:56 http://blog.9un.org
//============================================================================== 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using RuanRang.Core.Common;
using RuanRang.Core.Utility;

namespace RuanRang.Core
{
    public  abstract  class DocumentRender : IDocumentRender
    {
        /// <summary>
        /// Gets or sets the type of the target.
        /// </summary>
        /// <value>The type of the target.</value>
        public Type TargetType { get; protected set; }

        /// <summary>
        /// Gets or sets the target file.
        /// </summary>
        /// <value>The target file.</value>
        public object TargetFile { get; protected set; }

        /// <summary>
        /// Pages the count.
        /// </summary>
        /// <value>The page count.</value>
        ///   <returns>System.Int32.</returns>
        public int PageCount { get; protected set; }

        /// <summary>
        /// Occurs when [open completed].
        /// </summary>
        public event EventHandler<EventArgs> OpenCompleted;

        /// <summary>
        /// Called when [open completed].
        /// </summary>
        /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected virtual void OnOpenCompleted(EventArgs args)
        {
            var handler = OpenCompleted;
            if (handler != null) handler(this, args);
        }

        /// <summary>
        /// Occurs when [get image completed].
        /// </summary>
        public event EventHandler<EventArgs> GetImageCompleted;

        /// <summary>
        /// Called when [get image completed].
        /// </summary>
        /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected virtual void OnGetImageCompleted(EventArgs args)
        {
            var handler = GetImageCompleted;
            if (handler != null) handler(this, args);
        }

        /// <summary>
        /// Occurs when [save completed].
        /// </summary>
        public event EventHandler<EventArgs> SaveCompleted;

        /// <summary>
        /// Called when [save completed].
        /// </summary>
        protected virtual void OnSaveCompleted()
        {
            var handler = SaveCompleted;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Opens the specified file path.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public abstract void Open(string filePath);

        /// <summary>
        /// Opens the async.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        public virtual void OpenAsync(string filePath)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                Open((string)state);
                OnOpenCompleted(EventArgs.Empty);
            }, filePath);
        }

        /// <summary>
        /// Gets the image.
        /// </summary>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="resolution">The resolution.</param>
        /// <returns>Bitmap.</returns>
        public abstract Image GetImage(int pageIndex, float resolution = 100);

        /// <summary>
        /// Gets the image async.
        /// </summary>
        /// <param name="pageIndex">Index of the page.</param>
        /// <param name="resolution">The resolution.</param>
        public virtual void GetImageAsync(int pageIndex, float resolution = 100)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                var image = GetImage(pageIndex, resolution);
                var imageDict = new Dictionary<int, Image> { { pageIndex, image } };
                var args = new ImageEventArgs { ImageDictionary = imageDict, Resolution = resolution };
                OnGetImageCompleted(args);
            });
        }

        /// <summary>
        /// Gets the image.
        /// </summary>
        /// <param name="resolution">The resolution.</param>
        /// <returns>Image[][].</returns>
        public virtual Image[] GetImage(float resolution = 100)
        {
            var images = new Image[PageCount];
            for (var i = 0; i < PageCount; i++)
            {
                var bmp = GetImage(i, resolution);
                images[i] = bmp;
            }
            return images;
        }

        /// <summary>
        /// Gets the image async.
        /// </summary>
        /// <param name="resolution">The resolution.</param>
        public virtual void GetImageAsync(float resolution = 100)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                var images = GetImage(resolution);
                var imageDict = new Dictionary<int, Image>();
                for (var i = 0; i < images.Length; i++)
                {
                    imageDict.Add(i, images[i]);
                }
                var args = new ImageEventArgs { ImageDictionary = imageDict, Resolution = resolution };
                OnGetImageCompleted(args);
            });
        }

        /// <summary>
        /// Saves the specified save to folder.
        /// </summary>
        /// <param name="saveToFolder">The save to folder.</param>
        /// <param name="baseName">Name of the base.</param>
        /// <param name="waterImagePath">The water image path.</param>
        /// <param name="resolution">The resolution.</param>
        /// <param name="imageFormat">The image format.</param>
        public virtual void Save(string saveToFolder, string baseName, string waterImagePath = null,
                                  float resolution = 100,
                                  ImageFormat imageFormat = null)
        {
            if (!Directory.Exists(saveToFolder))
            {
                Directory.CreateDirectory(saveToFolder);
            }

            if (waterImagePath != null && !File.Exists(waterImagePath))
            {
                throw new IOException("水印图片文件不存在，路径：" + waterImagePath);
            }
            var images = GetImage(resolution);
            for (var i = 0; i < images.Length; i++)
            {
                var img = images[i];
                var fileName = string.Format("{0}\\{1}_{2}.{3}", saveToFolder, baseName, i, (imageFormat ?? ImageFormat.Jpeg).ToString().ToLower());
                if (img == null)
                {
                    continue;
                }
                if (waterImagePath != null)
                {
                    ImageWaterParser.AddImageSignPic(img, fileName, waterImagePath, 1, 100, 10);
                }
                else
                {
                    images[i].Save(fileName, imageFormat ?? ImageFormat.Jpeg);
                }
            }
        }

        /// <summary>
        /// Gets the image async.
        /// </summary>
        /// <param name="saveToFolder">The save to folder.</param>
        /// <param name="baseName">Name of the base.</param>
        /// <param name="waterImagePath">The water image path.</param>
        /// <param name="resolution">The resolution.</param>
        /// <param name="imageFormat">The image format.</param>
        public virtual void SaveAsync(string saveToFolder, string baseName, string waterImagePath = null,
                                       float resolution = 100,
                                       ImageFormat imageFormat = null)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                Save(saveToFolder, baseName, waterImagePath, resolution);
                OnSaveCompleted();
            });
        }
    }
}
